package com.mytecblog.framework.dao.query;

import com.mytecblog.framework.entity.MetaObject;

import com.mytecblog.framework.util.QueryUtil;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.Session;
import org.hibernate.query.Query;

import java.util.*;

/**
 * @author yg.huang
 * @version v1.0
 *          DATE  2016/10/28
 */
public class HQLDBQuery<T extends MetaObject>   implements DBQuery<T>{

    /**
     * 分页第一条记录索引
     */
    protected int firstResult = 0;
    /**
     * 分页最大结果数量
     */
    protected int maxResult = 2147483647;

    /**
     * 查询hql
     */
    protected String queryStr;
    /**
     * 排序字符串
     */
    protected String orderBy;
    /**
     * 默认排序字符串
     */
    protected String defaultOrderBy;
    /**
     * 参数集
     */
    protected Map<String,Object> paramsMap = new HashMap<String, Object>();
    /**
     * 查询参数数组
     */
    protected Object[] params;
    /**
     * 查询实体类
     */
    protected Class entityClass;
    protected  Session session;


    public HQLDBQuery(Class<T> entityClass, String queryStr,Session session) {

        this.queryStr = queryStr;

        this.entityClass=entityClass;
        this.session=session;
    }

    protected Query createDataQuery(Session session) {
        return session.createQuery(this.queryStr + this.generateOrderByStr());
    }



    /**
     * 得到查询结果数量
     * @return
     */
    public int getResultCount() {
        Query query = this.createDataQuery(this.session);
        HashMap notNullParams = new HashMap();
        for (Map.Entry<String, Object> entry : this.paramsMap.entrySet()) {
            if (entry.getValue() == null) {
                query.setParameter(entry.getKey(), entry.getValue());
            } else {
                notNullParams.put(entry.getKey(), entry.getValue());
            }
        }
        query.setProperties(notNullParams);
        List result = query.list();
        int count = ((Number) result.get(0)).intValue();
        return count;

    }

    public List<T> getResult() {
        List<T> result = new ArrayList<T>();
        Query query = this.createDataQuery(this.session);
        if(paramsMap.size()>0){
            HashMap notNullParams = new HashMap();
            for (Map.Entry<String, Object> entry : this.paramsMap.entrySet()) {
                if (entry.getValue() == null) {
                    query.setParameter(entry.getKey(), entry.getValue());
                } else {
                    notNullParams.put(entry.getKey(), entry.getValue());
                }
            }
            query.setProperties(notNullParams);
        }
        if(params!=null&&params.length>0){
            QueryUtil.setParameters(query,params);
        }

        if (this.firstResult > 0) {
            query.setFirstResult(this.firstResult);
            query.setMaxResults(this.maxResult);
        }

        result = query.list();
        return result;

    }
    public T uniqueResult() {

        List<T> results=this.getResult();
        return results.size()>0?results.get(0):null;
    }
    protected Query createCountQuery(Session session) {
        return session.createQuery("select count(*) from " + this.entityClass.getName() + " a_ where " + this.queryStr);
    }

    protected String generateOrderByStr() {
        return StringUtils.isBlank(this.orderBy)?(StringUtils.isBlank(this.defaultOrderBy)?"":" order by " + this.defaultOrderBy):" order by " + this.orderBy;
    }



    public String getQueryString() {
        return this.queryStr;
    }

    public void setFirstResult(int firstResult) {
        this.firstResult = firstResult;
    }

    public void setMaxResult(int maxResult) {
        this.maxResult = maxResult;
    }



    public DBQuery setParameter(String parameter, Object value) {
        this.paramsMap.put(parameter, value);
        return this;
    }

    public DBQuery setParameters(Map parameters) {
        this.paramsMap.putAll(parameters);
        return this;
    }
    public DBQuery setParameters(Object[] parameters) {
        this.params=parameters;
        return this;
    }

    public Map getParameters() {
        return this.paramsMap;
    }

    public void setDefaultOrderBy(String defaultOrderBy) {
        this.defaultOrderBy = defaultOrderBy;
    }



    public void setOrderBy(String orderBy) {
        this.orderBy = orderBy;
    }
}
